from docx import Document
from docx.oxml.ns import qn  # 导入qn
from docx.shared import Pt, Cm, RGBColor
from docx.enum.style import WD_STYLE_TYPE
from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_TAB_ALIGNMENT
from docx.oxml import OxmlElement
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from common import Result
import json
import logging
import os


LOGGER = logging.getLogger(__name__)

THESIS_EXPORT_BASE = "/docx/"

FONT_SONG = "宋体"
FONT_HEI = "黑体"
FONT_MSYH = "微软雅黑"


class ThesisDocx:
    def __init__(self) -> None:
        self.title = ""
        self.doc = Document()
        self.doc.styles["Normal"].font.size = Pt(12)
        self.doc.styles["Normal"].font.color.rgb = RGBColor(0, 0, 0)
        self.doc.styles["Normal"].font.name = FONT_SONG
        self.doc.styles["Normal"].element.rPr.rFonts.set(qn("w:eastAsia"), FONT_SONG)

        fontSizeArr = [24, 24, 18, 12, 12, 12]
        for i in range(1, 5):
            style = self.doc.styles[f"Heading {i}"]
            fontSize = fontSizeArr[i]

            style.font.size = Pt(fontSize)
            style.font.color.rgb = RGBColor(0, 0, 0)
            style.font.name = FONT_HEI
            style.element.rPr.rFonts.set(qn("w:eastAsia"), FONT_HEI)

        # # 页边距
        section = self.doc.sections[0]
        section.left_margin = Cm(2)
        section.right_margin = Cm(2)
        section.top_margin = Cm(2)
        section.bottom_margin = Cm(2)

    def addDigest(
        self,
        digest: str,
        digestEn: str,
        keywords: str = "关键字1，关键字2",
        keywordsEn: str = "Kw1,kw2",
    ):

        # 中文摘要
        paragraph = self.__addPara(isCenter=True)
        self.__addRun(paragraph, text="摘    要", fontName="黑体", fontSize=16)

        if digest is not None:
            digestArray = digest.split("\n")
            for dig in digestArray:
                if str(dig).strip() == "":
                    continue
                paragraph = self.__addPara(style="zhengwen")
                self.__addRun(
                    paragraph, text=str(dig).strip(), fontSize=12, fontName="宋体"
                )

        self.addBlanckLine()
        paragraph = self.__addPara()
        self.__addRun(
            paragraph, text=f"关键字：{keywords}", fontSize=12, fontName="宋体"
        )
        self.addPageBreak()

        # 英文摘要
        paragraph = self.__addPara(isCenter=True)
        self.__addRun(paragraph, text="ABSTRACT", fontName="黑体", fontSize=16)

        if digestEn is not None:
            digestArray = digestEn.split("\n")
            for dig in digestArray:
                if str(dig).strip() == "":
                    continue
                paragraph = self.__addPara(style="zhengwen")
                self.__addRun(
                    paragraph, text=str(dig).strip(), fontSize=12, fontName="宋体"
                )

        self.addBlanckLine()
        paragraph = self.__addPara()
        self.__addRun(
            paragraph, text=f"KEYWORDS : {keywordsEn}", fontSize=12, fontName="宋体"
        )

    def addPageBreak(self):
        self.doc.add_page_break()

    def __addRun(
        self,
        paragraph,
        text: str,
        fontSize: int = 12,
        isBold: bool = False,
        fontName: str = "宋体",
        underLine: bool = False,
        isRed: bool = False,
    ):
        run = paragraph.add_run(text)
        if fontSize > 0:
            run.font.size = Pt(fontSize)
        run.font.color.rgb = RGBColor(0, 0, 0)
        run.font.bold = isBold
        run.font.name = fontName
        run._element.rPr.rFonts.set(qn("w:eastAsia"), fontName)
        run.underline = underLine
        run.font.color.rgb = RGBColor(0, 0, 0)

        if isRed:
            run.font.color.rgb = RGBColor(204, 0, 0)

    def __addPara(self, isCenter=False, style=None):
        paragraph = self.doc.add_paragraph()
        if isCenter:
            paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER

        if style == "zhengwen":
            paragraph.paragraph_format.line_spacing = 1.5
            # 段落10个像素
            paragraph.paragraph_format.space_after = Pt(10)
            # 首行缩进
            paragraph.paragraph_format.first_line_indent = paragraph.style.font.size * 2
        return paragraph

    def addTail(self, reference: str, thanks: str):
        self.addPageBreak()

        # 参考文
        paragraph = self.__addPara(isCenter=True)
        self.__addRun(paragraph, text="参考文献", fontName="黑体", fontSize=16)
        paragraph = self.__addPara(style="zhengwen")
        self.__addRun(paragraph, text=reference)
        # 分页
        self.addPageBreak()
        # 附录
        paragraph = self.__addPara(isCenter=True)
        self.__addRun(paragraph, text="附录A XXXXX", fontName="黑体", fontSize=16)
        # 分页
        self.addPageBreak()
        # 致谢页
        paragraph = self.__addPara(isCenter=True)
        self.__addRun(paragraph, text="致    谢", fontName="黑体", fontSize=16)
        paragraph = self.__addPara(style="zhengwen")
        self.__addRun(paragraph, text=thanks)

    def addCover(self, title):
        self.title = title
        self.addBlanckLine()

        paragraph = self.__addPara(isCenter=True)
        self.__addRun(
            paragraph,
            text="⛪🏛️⛪",
            fontSize=48,
            isBold=True,
            fontName="黑体",
        )

        paragraph = self.__addPara(isCenter=True)
        self.__addRun(
            paragraph,
            text="XX(毕业|期末|结课|试验)设计(论文)报告",
            fontSize=26,
            isBold=True,
            fontName="黑体",
        )
        paragraph = self.__addPara(isCenter=True)
        text = "免责声明：本文不是正式论文！不具有任何学术效力。本文的目的是:提供相关素材和参考内容，不对专业论文撰写构成任何建议和指导。"
        self.__addRun(paragraph, text, fontSize=12, fontName="微软雅黑", isRed=True)

        paragraph = self.__addPara(isCenter=True)
        self.__addRun(paragraph, text=f"题目：", fontSize=22, fontName="黑体")
        self.__addRun(
            paragraph, text=f"\t{title}\t", fontSize=22, fontName="黑体", underLine=True
        )

        arr = [
            "学   号：",
            "姓   名：",
            "学   院：",
            "专   业：",
            "指导教师：",
            "起止日期：",
        ]
        for i in arr:
            paragraph = self.__addPara(isCenter=True)
            self.__addRun(paragraph, text=i, fontSize=18, fontName="宋体")
            self.__addRun(
                paragraph,
                text="\t\t\t\t\t",
                fontSize=18,
                fontName="宋体",
                underLine=True,
            )

    def addBlanckLine(self, i: int = 1):
        for i in range(0, i):
            self.doc.add_paragraph()

    def setAuthor(self, author):
        self.author.append(author)

    def addToc(self):
        paragraph = self.__addPara(isCenter=True)
        self.__addRun(paragraph, text="目   录", fontName="黑体", fontSize=18)

        paragraph = self.doc.add_paragraph()
        run = paragraph.add_run()
        fldChar = OxmlElement("w:fldChar")  # creates a new element
        fldChar.set(qn("w:fldCharType"), "begin")  # sets attribute on element
        instrText = OxmlElement("w:instrText")
        instrText.set(qn("xml:space"), "preserve")  # sets attribute on element
        instrText.text = 'TOC \o "1-3" \h \z \\u'

        fldChar2 = OxmlElement("w:fldChar")
        fldChar2.set(qn("w:fldCharType"), "separate")
        fldChar3 = OxmlElement("w:t")
        fldChar3.text = (
            "此处为目录，需要手动触发更新。请在此点击鼠标右键，选择菜单中的'更新域'"
        )
        fldChar2.append(fldChar3)

        fldChar4 = OxmlElement("w:fldChar")
        fldChar4.set(qn("w:fldCharType"), "end")

        r_element = run._r
        r_element.append(fldChar)
        r_element.append(instrText)
        r_element.append(fldChar2)
        r_element.append(fldChar4)

    def addContentParagraph(self, title, text, level=1):
        if title is None or title == "":
            LOGGER.info("title 为空 跳过")
            return
        head = self.doc.add_heading("", level)
        if level == 1:
            head.alignment = WD_ALIGN_PARAGRAPH.CENTER

        self.__addRun(paragraph=head, text=title, fontName="黑体", fontSize=-1)

        if text is None or text == "":
            return

        textArr = str(text).split("\n")
        for textFragment in textArr:
            textFragment = textFragment.strip()
            if textFragment == "":
                continue
            paragraph = self.__addPara(style="zhengwen")
            self.__addRun(paragraph, textFragment, fontSize=12, fontName="宋体")

    def refreshHeadNo(self):
        head1 = 0
        head2 = 0
        head3 = 0
        for para in self.doc.paragraphs:
            styleName = para.style.name
            if styleName == "Heading 1":
                head1 += 1
                for i in range(len(para.runs)):
                    para.runs[i].text = para.runs[i].text.replace(
                        para.text, str(head1) + " " + para.text
                    )
                head2 = 0
                head3 = 0
            if styleName == "Heading 2":
                head2 += 1
                for i in range(len(para.runs)):
                    para.runs[i].text = para.runs[i].text.replace(
                        para.text, str(head1) + "." + str(head2) + " " + para.text
                    )

    def setHeader(self):
        section = self.doc.sections[0]
        header = section.header
        paragraph = header.paragraphs[0]
        paragraph.text = f"\t{self.title}\t"

        # 首页不要页眉
        section.different_first_page_header_footer = True
        section.first_page_header.paragraphs[0].text = ""

    # 添加页脚，格式为：第 n 页 共 m 页
    def setFooter(self, font_name, font_size):
        # 添加一个节（Section）并获取页脚
        section = self.doc.sections[0]
        footer = section.footer

        # 在页脚添加一个段落
        paragraph = footer.paragraphs[0]
        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  # 设置居中对齐

        # 添加文本 "第"
        run1 = paragraph.add_run("第 ")
        font1 = run1.font
        font1.name = font_name
        font1.size = Pt(font_size)  # 设置字体大小
        run1._element.rPr.rFonts.set(qn("w:eastAsia"), font_name)

        # 添加页码相关的字段
        run2 = paragraph.add_run("")
        fldChar2 = OxmlElement("w:fldChar")
        fldChar2.set(qn("w:fldCharType"), "begin")
        run2._element.append(fldChar2)

        run3 = paragraph.add_run("")
        fldChar3 = OxmlElement("w:instrText")
        fldChar3.text = "PAGE"
        font3 = run3.font
        font3.name = "Times New Roman"
        font3.size = Pt(font_size)  # 设置字体大小
        run3._element.append(fldChar3)

        run4 = paragraph.add_run("")
        fldChar4 = OxmlElement("w:fldChar")
        fldChar4.set(qn("w:fldCharType"), "separate")
        run4._element.append(fldChar4)

        run5 = paragraph.add_run("")
        fldChar5 = OxmlElement("w:fldChar")
        fldChar5.set(qn("w:fldCharType"), "end")
        run5._element.append(fldChar5)

        # 添加文本 "页，共"
        run6 = paragraph.add_run(" 页 共 ")
        font6 = run6.font
        font6.name = font_name
        font6.size = Pt(font_size)  # 设置字体大小
        run6._element.rPr.rFonts.set(qn("w:eastAsia"), font_name)

        # 添加页数字段
        run7 = paragraph.add_run("")
        fldChar7 = OxmlElement("w:fldChar")
        fldChar7.set(qn("w:fldCharType"), "begin")
        run7._element.append(fldChar7)

        run8 = paragraph.add_run("")
        fldChar8 = OxmlElement("w:instrText")
        fldChar8.text = "NUMPAGES"
        font8 = run8.font
        font8.name = "Times New Roman"
        font8.size = Pt(font_size)  # 设置字体大小
        run8._element.append(fldChar8)

        run9 = paragraph.add_run("")
        fldChar9 = OxmlElement("w:fldChar")
        fldChar9.set(qn("w:fldCharType"), "separate")
        run9._element.append(fldChar9)

        run10 = paragraph.add_run("")
        fldChar10 = OxmlElement("w:fldChar")
        fldChar10.set(qn("w:fldCharType"), "end")
        run10._element.append(fldChar10)

        # 添加文本 "页"
        run11 = paragraph.add_run(" 页")
        font11 = run11.font
        font11.name = font_name
        font11.size = Pt(font_size)  # 设置字体大小
        run11._element.rPr.rFonts.set(qn("w:eastAsia"), font_name)

    def export(self, fileName) -> Result:
        try:
            self.refreshHeadNo()
            self.setFooter(font_name="宋体", font_size=12)
            self.setHeader()
            absPath = os.getcwd() + THESIS_EXPORT_BASE + fileName
            LOGGER.info(absPath)
            self.doc.save(absPath)
            return Result()
        except Exception as e:
            LOGGER.exception(e)
            return Result().error(e)
